<?php

/**
 * Применяет рекурсивно ко всем элементам массива указанную функцию и изменяет
 * значение элемента на результат.
 *
 * @param   array   $input
 * @param   callback    $funcname
 */
function array_apply_recursive(&$input, $funcname) {
    array_walk_recursive($input, create_function('&$value', '$value = ' . $funcname . '($value);'));
}

/**
 * Проверяет, есть ли элемент с указанным значением в массиве. Массив обходится
 * рекурсивно.
 *
 * @param   array   $needle
 * @param   mixed   $haystack
 * @return  boolean
 */
function in_array_recursive($needle, $haystack) {
    foreach ($haystack as $value) {
        if (is_array($value)) {
            if (in_array_recursive($needle, $value)) {
                return true;
            }
        }
        elseif ($value == $needle) {
            return true;
        }
    }
    return false;
}

/**
 * Возвращает ключи элементов массива, значения которых не являются массивом
 * (т.е. являются листьями дерева).
 *
 * @param   array   $input
 * @return  array
 */
function array_keys_recursive($input) {
    $keys = array();
    foreach ($input as $key => $value) {
        $keys = array_merge($keys, is_array($value) ? array_keys_recursive($value) : array($key));
    }
    return array_unique($keys);
}

/**
 * Разворачивает сложный массив в плоский. Может быть использован для методов,
 * которые принимают переменное число аргументов как в массиве, так и по отдельности.
 *
 * @param   array   $input
 * @return  array
 */
function array_values_recursive($input) {
    $values = array();
    foreach ($input as $value) {
        $values = array_merge($values, is_array($value) ? array_values_recursive($value) : array($value));
    }
    return $values;
}

/**
 * Возвращает элементы массива только с указанными ключами, при этом ключи
 * результирующего массива располагаются в указанном порядке.
 *
 * @param   array   $input
 * @param   array   $keys
 * @param   mixed   $default
 * @return  array
 */
function array_extract($input, $keys, $default = null) {
    $result = array();
    $fill = func_num_args() > 2;
    foreach ($keys as $key) {
        if (array_key_exists($key, $input)) {
            $result[$key] = $input[$key];
        } elseif ($fill) {
            $result[$key] = $default;
        }
    }
    return $result;
}

/**
 * Возвращает, является ли указанный массив числовым.
 *
 * @param   array   $array
 * @return  boolean
 */
function is_numeric_array($array) {
    return is_array($array) && array_keys($array) === range(0, count($array) - 1);
}

/**
 * Возвращает значение элемента массива с указанным ключом либо значение по
 * умолчанию, если элемент не существует.
 *
 * @param   array   $array
 * @param   mixed   $key
 * @param   mixed   $default
 * @return  mixed
 */
function get_array_element($array, $key, $default = null) {
    return array_key_exists($key, $array) ? $array[$key] : $default;
}

/**
 * Возвращает расширение файла с указанным именем.
 *
 * @param   string  $filename
 * @return  string
 */
function get_extension($filename) {
    return strtolower(pathinfo($filename, PATHINFO_EXTENSION));
}

/**
 * Преобразует строку из нотации "foo-bar-baz" в "fooBarBaz".
 *
 * @param   string  $string
 * @return  string
 */
function str_camelize($string) {
    return preg_replace('/(^|\-)([a-z])/e', "strtoupper('\\2')", $string);
}

/**
 * В указанном ассоциативном массиве перемещает элемент с указанным ключом на
 * указанную позицию.
 *
 * @param   array   $input
 * @param   mixed   $key
 * @param   integer $position
 * @return  boolean
 */
function array_set_element_position(&$input, $key, $position) {
    if (false === ($current = array_search($key, array_keys($input)))
        || $current == $position) {
        return false;
    }

    switch (true) {
        case $current < $position;
            $slices = array(
                array_slice($input, 0, $current),
                array_slice($input, $current + 1, $position - $current),
                array_slice($input, $current, 1),
                array_slice($input, $position),
            );
            break;
        case $current > $position;
            $slices = array(
                array_slice($input, 0, $position),
                array_slice($input, $current, 1),
                array_slice($input, $position, $current - $position),
                array_slice($input, $current),
            );
    }
    $input = call_user_func_array('array_merge', $slices);
    return true;
}

/**
 * Возвращает значение указанной директивы конфигурации в байтах.
 *
 * @param   string  $varname
 * @return  integer
 */
function ini_get_bytes($varname) {
   $value = trim(ini_get($varname));
   $last = strtolower($value{strlen($value)-1});
   switch ($last) {
       case 'g':
           $value *= 1024;
       case 'm':
           $value *= 1024;
       case 'k':
           $value *= 1024;
   }
   return (int)$value;
}

/**
 * Преобразует целочисленное значение в массив значений 2^N, которые в сумме
 * дают это значение.
 *
 * @param   integer  $value
 * @return  array
 */
function dec2array($value) {
    $bits = array();
    for ($i = strlen(($bin = decbin($value))); $i >= 0; $i--) {
        if (substr($bin, $i, 1)) {
            $bits[] = pow(2, $i);
        }
    }
    return $bits;
}

require dirname(__FILE__) . DIRECTORY_SEPARATOR . 'tmp_date.php';